package com.ld.security.common.mybatis.wrapper;

import cn.hutool.core.lang.Console;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableName;
import com.ld.security.common.core.util.ListUtil;
import com.ld.security.common.core.util.ReflectionUtil;
import com.ld.security.common.core.util.StringUtil;
import com.ld.security.common.mybatis.anno.*;
import com.ld.security.common.mybatis.constant.SqlCondition;
import com.ld.security.common.mybatis.util.SqlTool;
import org.springframework.core.annotation.AnnotationUtils;

import java.lang.reflect.Field;
import java.util.*;

/**
 * 实体sql构造器
 */
public class BaseQueryWrapper extends AbstQueryWrapper {

    //模板对象
    private Object arg;



    Class clazz;


    //分组后的字段
    private List<SqlTool.fieldVo> fieldList;

    private List<Field> fields;



    public BaseQueryWrapper(Object arg) {

        if(arg instanceof Class){
            clazz =(Class)arg;
            this.arg = ReflectionUtil.newInstance(clazz);
        }else{
            this.arg = arg;
            this.clazz=arg.getClass();
        }

        this.init();
    }


    @Override
    protected void init() {
        fieldList = SqlTool.groupField(arg.getClass());
        fields = new LinkedList<>();
        for (SqlTool.fieldVo fieldVo : fieldList) {
            fields.addAll(fieldVo.getFields());
        }

        super.init();
    }

    public String getColumnSql(){
        StringBuffer sb =   new StringBuffer();
        boolean b=false;
        for (Field field :fields) {
            SqlKey sqlKey =   field.getAnnotation(SqlKey.class);

            CollectKey collectKey = field.getAnnotation(CollectKey.class);

            if( sqlKey != null){
                if(!sqlKey.tableField()){
                    continue;
                }
            }else{

            }
            if(b){
                sb.append(" , ");
            }
            String name =null;
            if(sqlKey != null){
                name = sqlKey.name();
            }
            if(StringUtil.isNull(name)) {
                name = field.getName();
            }


                name=StringUtil.javaToColumn(name);

            if(collectKey != null){
                if(Date.class.isAssignableFrom(field.getType())){
                    String sql = "DATE_FORMAT("+name+","+collectKey.dateFunc().getFormatType()+") ";
                    sb.append(sql);
                }else if(Number.class.isAssignableFrom(field.getType())){
                    sb.append(collectKey.numberFunc().getValue() +"("+name+") ");
                }
                sb.append(" as " + field.getName());

            }else{
                sb.append(name+" as " + field.getName());
            }


            b=true;
        }

        this.columnSql = sb.toString();


        return sb.toString();
    }


    private String getEntitySql(){
        TableName tableName =   AnnotationUtils.findAnnotation(clazz,TableName.class);
        if(tableName == null){
            return null;
        }

        return tableName.value();
    }


    public String getJoinSql() {
        StringBuffer sb =   new StringBuffer();

        List<JoinKey> list =  new LinkedList<>();

        JoinKey x =  AnnotationUtils.findAnnotation(clazz,JoinKey.class);
        JoinKeys tableKeys =  AnnotationUtils.findAnnotation(clazz,JoinKeys.class);
        if(tableKeys != null){
            for (JoinKey tableKey : tableKeys.value()) {
                list.add(tableKey);
            }
        }else if(x != null){

            list.add(x);
        }


        for (JoinKey tableKey : list) {
            sb.append(tableKey.tableX());
            sb.append(" left join ");
            sb.append(tableKey.tableY());

            sb.append(" on ");

            sb.append("  "+tableKey.on()+" ");

        }


        return sb.toString();
    }

    public String getFormSql(){
        //兼容语法处理
        fromSql =  this.getEntitySql(); ;
        if(StringUtil.isNull(fromSql)){
            fromSql =  this.getJoinSql();
        }

        return fromSql;

    }

  private String getWhereSql(SqlTool.fieldVo fieldVo) {
      StringBuffer sb =   new StringBuffer();
      for (Field field : fieldVo.getFields()) {

          SqlKey sqlKey = field.getAnnotation(SqlKey.class);
          CollectKey collectKey = field.getAnnotation(CollectKey.class);
          if (sqlKey == null) {
              continue;
          }else if(collectKey != null){
              continue;
          }else if(sqlKey.value() == SqlCondition.anon){
              continue;
          }

          String valField = sqlKey.valueField();
          if(StringUtil.isNull(valField)){
              valField = field.getName();
          }



          Object val =  ReflectionUtil.invokeGetter(arg,valField);

          if(ReflectionUtil.isNull(val)){
              continue;
          }
          if(sb.length() !=  0){
              if(sqlKey.and()){
                  sb.append(" and ");
              }else{
                  sb.append(" or ");
              }
          }
          String name = sqlKey.name();


          if(StringUtil.isNull(name)){
              name=field.getName();
          }
          name=StringUtil.javaToColumn(name);


          String sql = this.getValue(name,sqlKey.value(),val);
          sb.append(sql);
      }
      return sb.toString();
  }

    public String getWhereSql() {

        StringBuffer sb =   new StringBuffer();

        boolean init = false;
    for (SqlTool.fieldVo fieldVo : fieldList) {

        String sql =this.getWhereSql(fieldVo);
        if(StringUtil.isNull(sql)){
            continue;
        }

        if(sb.length() != 0){
            sb.append(" and ");
        }
        if(fieldList.size()>1){
            sb.append("( ");
        }
        sb.append(sql);
        if(fieldList.size()>1){
            sb.append(")");
        }
        init=true;
    }
    this.whereSql = sb.toString();


        return whereSql;
    }

    public String getGroupSql(){
        StringBuffer sb =   new StringBuffer();


            for (Field field :fields) {

              GroupKey groupKey = field.getAnnotation(GroupKey.class);
              if (groupKey == null) {
                continue;
              }
              if (sb.length() != 0) {
                sb.append(" , ");
              }
                String name =field.getName();
                sb.append(name);


            this.groupSql=sb.toString();
            }
        return sb.toString();
    }

    public String getHavingSql(){

        StringBuffer sb =   new StringBuffer();


        for (Field field : fields) {
          SqlKey sqlKey = field.getAnnotation(SqlKey.class);
            CollectKey collectKey = field.getAnnotation(CollectKey.class);
          if (sqlKey == null) {
            continue;
          } else if (collectKey == null) {
            continue;
          }else if(sqlKey.value() == SqlCondition.anon){
              continue;
          }

            String valField = sqlKey.valueField();
            if(StringUtil.isNull(valField)){
                valField = field.getName();
            }


            Object val =  ReflectionUtil.invokeGetter(arg,valField);
            if(ReflectionUtil.isNull(val)){
                continue;
            }
          if(sb.length() != 0){
                if(sqlKey.and()){
                    sb.append(" and ");

                }else{
                    sb.append(" or ");
                }

          }

            String name = sqlKey.name();

        //    if(StringUtil.isNull(name)){
                name=field.getName();
          //  }
           // name=StringUtil.javaToColumn(name);


            SqlCondition sqlCondition =  sqlKey.value();

            sb.append(
                this.getValue(name,sqlCondition,val)
            );
           // sb.append(name+"  "+sqlCondition.getLabel()+this.getValue(field.getName(),"", sqlCondition,val));


        }
        this.havingSql=sb.toString();
        return sb.toString();
    }

    public String getOrderSql(){
        StringBuffer sb =   new StringBuffer();


        for (Field field : fields) {
            OrderBy orderBy =  field.getAnnotation(OrderBy.class);
            if(orderBy == null){
                continue;
            }
            if(sb.length() != 0 ){
                sb.append(" , ");
            }
            sb.append(orderBy.value() );
            if(orderBy.asc()){
                sb.append(" asc ");
            }else{
                sb.append(" desc ");
            }

        }
        this.orderSql=sb.toString();
        return this.orderSql;
    }



    public Object getArg() {
        return arg;
    }
    public BaseQueryWrapper order(String name, boolean asc) {
        if(orderSql.length() != 0){
            orderSql+=" , ";
        }
        orderSql+=name;
        if(asc){
            orderSql+=" asc ";
        }else{
            orderSql+=" desc ";
        }
        return this;
    }
    public BaseQueryWrapper where(String name, SqlCondition sqlCondition, Object val) {
        return where(name,sqlCondition,val,true);
    }

        public BaseQueryWrapper where(String name, SqlCondition sqlCondition, Object val, boolean and){
        if(ReflectionUtil.isNull(val)){
            return this;
        }
        //高维化一维
        if(val instanceof Collection){
            val = ListUtil.listMapOne((Collection)val);
        }

        if(StringUtil.isNull(whereSql)){
            whereSql=" ";
        }else{
            if(and){
                whereSql+=" and ";
            }else{
                whereSql+=" or ";
            }

        }




        //关键字替换

        whereSql+= this.getValue(name,sqlCondition,val);


        return this;
    }






}